#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>


#define MAXLINE 4096

int main()
{
	int listen_fd, conn_fd;
	socklen_t cli_len;
	struct sockaddr_in serv_addr, cli_addr;
	listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	serv_addr.sin_port = htons(15555);

	bind(listen_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

	listen(listen_fd, 1024);

	char recv_line[MAXLINE], send_line[MAXLINE];
	int read_len;

	fd_set readmask;
	fd_set allreads;
	FD_ZERO(&allreads);
	FD_SET(0, &allreads);
	FD_SET(listen_fd, &allreads);

	int fd_max = listen_fd;

	for(;;) {
		readmask = allreads;

		int rc = select(listen_fd + 1, &readmask, NULL, NULL, NULL);

		if (rc <= 0) {
			fprintf(stdout, "select create failed\n");
			break;
		}

		for (int i = 0; i < fd_max + 1; ++i) {
			if (FD_ISSET(i, &readmask)) {
				if (i == listen_fd) {
					cli_len = sizeof(cli_addr);
					conn_fd = accept(listen_fd, (struct sockaddr *)&cli_addr, &cli_len);
					FD_SET(conn_fd, &allreads);
					if (fd_max < conn_fd)
						fd_max = conn_fd;
					fprintf(stdout, "connection %d!!\n", conn_fd);					
					// read_data(conn_fd);
					// close(conn_fd);
				} else {
					fprintf(stdout, "read %d client!!\n", i);
					read_len = read(i, recv_line, MAXLINE);
					fprintf(stdout, "recv_line %s client!!\n", recv_line);
					if (read_len == 0) {
						FD_CLR(i, &allreads);
						close(i);
						fprintf(stdout, "close %d client!!\n", i);
					} else {
						write(i, recv_line, MAXLINE);
					}
				}

			}
		}
	}

	close(listen_fd);
	return 0;
}


// void read_data(int sockfd) {
// 	size_t n;
// 	char buf[1024];
// 	int times = 0;

// 	for (;;) {
// 		fprintf(stdout, "block in read\n");

// 		if ((n = readn(sockfd, buf, 1024) == 0)) {
// 			return;
// 		}

// 		times++;
// 		fprintf(stdout, "1K read for %d \n", times); 
// 		usleep(1000);
// 	}
// }

// size_t readn(int sockfd, char *buf, size_t size) {
// 	char *pbuf = buf;
// 	int length = size;

//     while (length > 0) {
//     	int read_len = read(sockfd, buf, length);

//     	if (read_len < 0) {
//     		if (errno == EINTR)
//     			continue;
//     		else
//     			return (-1);
//     	} else if (read_len == 0)
//     		break;

//     	length -= read_len;
//     	buf += read_len;
//     }

//     return (size - length);
// }